package cc.buttfu.thingbento;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.htmlcleaner.HtmlCleaner;
import org.htmlcleaner.TagNode;

import android.accounts.NetworkErrorException;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;

/**
 * @author dislink.now
 * 
 * PageLoader for the status update page. Reads in the shouts page,
 * parses it and turns it into an array of Posts.
 *
 */
public class ShoutLoader implements PageLoader {

	String page = "";
	ArrayList<Post> posts;
	private boolean finished = false;
	private final String baseUrl = "http://thingbox.com/members/statuses";
	private Context context;
	
	/**
	 * @param context
	 * @param page The page suffix - i.e. "?page=2" etc.
	 * @throws NotLoggedInException
	 * @throws NetworkErrorException
	 * @throws NagScreenException
	 */
	public ShoutLoader(Context context, String page) throws NotLoggedInException, NetworkErrorException, NagScreenException {
		this.context = context;
		posts = new ArrayList<Post>();
		
		setPage(page);
	}

	public Post getPost(int index) {
		return posts.get(index);
	}

	public ArrayList<Post> getPosts() {
		return posts;
	}

	/* (non-Javadoc)
	 * @see cc.buttfu.thingbento.PageLoader#setPage(java.lang.String)
	 */
	public void setPage(String page) throws NotLoggedInException, NetworkErrorException, NagScreenException {
		this.page = page;
		
		HttpClient client = new DefaultHttpClient();
		HttpGet httpget = new HttpGet(baseUrl + page);

		SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);

		String cookie = prefs.getString("cookie", "");
		if( cookie.equals("") )
			throw new NotLoggedInException();
		
		httpget.setHeader("Cookie", cookie);
		HttpResponse response;
		
		try {
			response = client.execute(httpget);
			InputStream contentStream = response.getEntity().getContent();
			
			HtmlCleaner cleaner = new HtmlCleaner();
			TagNode tn = cleaner.clean(contentStream);
			
			TagNode[] subscribes = tn.getElementsByAttValue("class", "subscribe", true, true);
			if( subscribes.length > 0 )
				throw new NagScreenException();
			
			TagNode[] notices = tn.getElementsByAttValue("id", "notices", true, true);
			
			if( notices.length > 0 && notices[0].getAttributes().containsValue("warning") )
				throw new NotLoggedInException();
			
			TagNode[] twattles = tn.getElementsByAttValue("id", "twattle", true, true);
			
			for( TagNode t : twattles ){

				Post post = new Post();
				
				/* Each element with class "speech" contains a single shout */
				post.setText( t.findElementByAttValue("class", "speech", true, true).
						getText().toString().replaceAll("\\s+", " ") );
				
				/* "subtle small meta" class elements contain meta-data about the shout */
				TagNode u = t.findElementByAttValue("class", "subtle small meta", true, true);
				
				/* We're only interested in the username 
				 * TODO: extract the date too.
				 * */
				while( u.getChildren().size() > 1 ){
					u.removeChild( u.getChildren().get(1));
				}
				
				/* TODO: there are some whitespace characters that remain at beginning
				 * and end. Why? */
				post.setUsername( u.getText().toString().replaceAll("\\s+", " ").
						replace("^\\s", "").replace("\\s$", "").replace("said this", "") );
				
				/* The ImageLoader will take care of actually loading the image later */
				post.setThumbnail( t.findElementByAttValue("class", "headshot", true, true).
						getAttributeByName("src") );
				posts.add(post);
				
			}
			
		} catch (ClientProtocolException e) {
			e.printStackTrace();
			throw new NetworkErrorException();
		} catch (IOException e) {
			e.printStackTrace();
			throw new NetworkErrorException();
		}
		
		finished = true;
		
	}

	public int size() {
		return posts.size();
	}

	public boolean finished() {
		return finished;
	}


}
